package net.jltec.model.workflow.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.jltec.core.Constants;
import net.jltec.core.dao.IJDAO;
import net.jltec.core.exception.ProcedureException;
import net.jltec.core.service.BaseCommonService;
import net.jltec.core.utils.RequestProcessorUtils;
import net.jltec.core.utils.SMSService;
import net.jltec.core.utils.Tools;
import net.jltec.core.utils.ValidateUtils;
import net.jltec.model.util.CommonProcessor;
import net.jltec.model.util.RequestContext;
import net.jltec.model.workflow.dao.WorkflowDao;
import net.jltec.model.workflow.dto.GoToNextDTO;
import net.jltec.model.workflow.dto.GoToNextForm;
import net.jltec.model.workflow.dto.StartFlowDTO;
import net.jltec.model.workflow.dto.VariableDTO;
import net.jltec.model.workflow.entity.WorkflowInstance;
import net.jltec.model.workflow.entity.WorkflowInstanceNode;
import net.jltec.model.workflow.entity.WorkflowInstanceTransition;
import net.jltec.model.workflow.entity.WorkflowInstanceVariable;
import net.jltec.model.workflow.entity.WorkflowTemplateCondition;
import net.jltec.model.workflow.entity.WorkflowTemplateDefinition;
import net.jltec.model.workflow.entity.WorkflowTemplateNode;
import net.jltec.model.workflow.entity.WorkflowTemplateNodeAction;
import net.jltec.model.workflow.entity.WorkflowTemplateTransition;
import net.jltec.model.workflow.entity.WorkflowTemplateVariable;
import net.jltec.model.workflow.service.IWorkflowService;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
import org.wltea.expression.ExpressionEvaluator;

import com.alibaba.fastjson.JSONArray;

@SuppressWarnings("unchecked")
public class WorkflowServiceImpl extends BaseCommonService implements IWorkflowService {
	private WorkflowDao workflowDao;
	private IJDAO jdao;
	
	private static Log log = LogFactory.getLog(WorkflowServiceImpl.class);

	public IJDAO getJdao() {
		return jdao;
	}

	public void setJdao(IJDAO jdao) {
		this.jdao = jdao;
	}

	public WorkflowDao getWorkflowDao() {
		return workflowDao;
	}

	public void setWorkflowDao(WorkflowDao workflowDao) {
		this.workflowDao = workflowDao;
	}
	
	//操作条件检查
	private boolean isType2Condition(List<WorkflowTemplateCondition> conditions,WorkflowInstance wi)
	{
		if (conditions.size()==0) return true;
		int joinsign = 0;
		boolean[] rets = new boolean[conditions.size()];
		
		boolean ret = false;
		for (int i=0;i<conditions.size();i++)
		{
			if (joinsign==0)
				joinsign = conditions.get(i).getJoinsign();	
			
			conditions.get(i).setDao(wi.getDao());
			WorkflowTemplateTransition tr = conditions.get(i).getTr();
			WorkflowInstanceTransition witr=this.getWorkflowDao().getWorkflowInstanceTransitionByTrId(wi.getWiid(),tr.getTrid());
			if (joinsign==1&&tr.getTrid()!=0&&null==witr)
			{
				return false;
			}else
			{
				
				rets[i] = isSingleCondition(conditions.get(i),wi);
				if (joinsign==2&&rets[i]) return true;
				//OR=2,1=AND
			}
		}
		
		if (joinsign==1)
		{
			ret = true;
			for (int k=0;k<rets.length;k++)
				ret = ret && rets[k];
		}
		
		return ret;
	}
	
	//单一条件判断
	private boolean isSingleCondition(WorkflowTemplateCondition condition,WorkflowInstance wi)
	{
		if(ValidateUtils.isNotNull(condition.getEvalcont())){
			List<WorkflowInstanceVariable> l = this.getWorkflowDao().getWorkflowInstanceVariableByWiId(wi.getWiid());
			String cont = condition.getEvalcont()+"";
			for(int i=0;i<l.size();i++){
				Double v = l.get(i).getValue();
				if(ValidateUtils.isNull(v))v=0d;
				cont=cont.replaceAll("#"+l.get(i).getEname()+"#",v.toString());
			}
			Object result = ExpressionEvaluator.evaluate(cont);
			return (Boolean)result;
		}
		else if(ValidateUtils.isNotNull(condition.getSqlcont())){
			List<WorkflowInstanceVariable> l = this.getWorkflowDao().getWorkflowInstanceVariableByWiId(wi.getWiid());
			Map p = new HashMap();
			p.put(wi.getFieldname(),wi.getBusid());
			String cont = condition.getSqlcont()+"";
			for(int i=0;i<l.size();i++){
				p.put(l.get(i).getEname(),l.get(i).getValue());
			}
			return ValidateUtils.isNotNull(jdao.queryForList(p,cont));
		}
		else{
			WorkflowInstanceVariable var1 = this.getWorkflowDao().getWorkflowInstanceVariableByWiidAndVarid(wi.getWiid(),condition.getVarid1());
			WorkflowInstanceVariable var2 = this.getWorkflowDao().getWorkflowInstanceVariableByWiidAndVarid(wi.getWiid(),condition.getVarid2());
			double value1=(null==var1.getValue()?0:var1.getValue().doubleValue());
			double value2=(null==var2.getValue()?0:var2.getValue().doubleValue());
			//1=大于,2=小于,3=大于等于,4=小于等于,5=等于
			if (condition.getCondsign()==1){
				if (value1-value2>0)
				{
					return true;
				}
			}
			if (condition.getCondsign()==2){
				if (value1-value2<0)
				{
					return true;
				}			
			}
			if (condition.getCondsign()==3){
				if (value1-value2>=0)
				{
					return true;
				}			
			}
			if (condition.getCondsign()==4){
				if (value1-value2<=0)
				{
					return true;
				}
			}
			if (condition.getCondsign()==5){
				if (value1-value2<0.001&&value1-value2>-0.001)
				{
					return true;
				}				
			}
		}
		return false;
	
	}
	
	//启动条件检查
	private boolean isType1Condition(List<WorkflowTemplateCondition> conditions,WorkflowInstance wi)
	{
		
		
		
		if (conditions.size()==0) return true;
		
		int joinsign = 0;
		boolean ret = false;
		
		boolean[] rets = new boolean[conditions.size()];
		
		for (int i=0;i<conditions.size();i++)
		{
			rets[i] = isSingleCondition(conditions.get(i),wi);
			if (joinsign==0)
				joinsign = conditions.get(i).getJoinsign();
			//OR=2,1=AND
			
		}
		
		if (joinsign==1)
		{
			ret = true;
			for (int i=0;i<rets.length;i++)
				ret = ret && rets[i];
		}
		if (joinsign==2)
		{
			for (int i=0;i<rets.length;i++)
			{
				if (rets[i]) return true;
			}
		}
		
		return ret;
	}
	
	//保存节点实例
	private WorkflowInstanceNode insertNodeData(WorkflowTemplateNode node,WorkflowInstance wi,int isEnd)
	{
		WorkflowInstanceNode win = new WorkflowInstanceNode();
		win.setCreateuser(wi.getCreateuser());
		win.setDao(wi.getDao());
		win.setIsend(isEnd);
		win.setIsreload(false);
		win.setManid(0);
		win.setNode(node);
		win.setNodeid(node.getNodeid());
		win.setVarid(node.getVarid());
		win.setWi(wi);
		win.setWiid(wi.getWiid());
		win.setType(node.getType());
		win.setName(node.getName());
		win.setVmlx(node.getVmlx());
		win.setVmly(node.getVmly());
		win.insert();			
		return win;
	}
	
	//保存连线实例
	private void insertTransitionData(WorkflowTemplateTransition trans,WorkflowInstanceNode fnode,WorkflowInstanceNode tnode,WorkflowInstance wi)
	{
		//插入转出线
		WorkflowInstanceTransition witr  = new WorkflowInstanceTransition();
		witr.setCreateuser(0);
		witr.setFnid(fnode.getWinid());
		witr.setTnid(tnode.getWinid());
		witr.setName(trans.getName());
		witr.setStatus(1);
		witr.setVmlctxy(trans.getVmlctxy());
		witr.setWiid(wi.getWiid());
		witr.setWtdid(wi.getWtdid());
		witr.setTrid(trans.getTrid());
		witr.setName(trans.getName());
		witr.setVmlctxy(trans.getVmlctxy());
		witr.setDao(wi.getDao());
		witr.insert();		
	}
	
	//由操作人将变量赋值到流程，替换流程现有变量值
	private void replaceVarDataValue(WorkflowInstanceVariable var,List<VariableDTO> list)
	{
		if (!var.isCoust())
		{
			for (int j=0;j<list.size();j++)
			{
				if (var.getEname().equals(list.get(j).getEname()))
				{
					var.setValue(list.get(j).getValue());
				}
			}
		}		
	}
	
	
	//保存实例变量
	private WorkflowInstanceVariable insertInstanceVariableData(WorkflowTemplateVariable tempvar,List<VariableDTO> list,WorkflowInstance wi)
	{

			WorkflowInstanceVariable var = new WorkflowInstanceVariable();
			var.setCname(tempvar.getCname());
			var.setCreateuser(0);
			var.setDao(wi.getDao());
			var.setEname(tempvar.getEname());
			var.setIsmod(tempvar.getIsmod());
			var.setIsnodeid(tempvar.getIsnodeid());
			var.setIsreload(false);
			var.setType(tempvar.getType());
			var.setValue(tempvar.getValue());
			var.setWiid(wi.getWiid());
			var.setVarid(tempvar.getVarid());
			
			replaceVarDataValue(var,list);
			
			var.insert();
			return var;

	}	
	

	
	//动态执行更新SQL语句
	private void execUpdateSql(String sql,boolean isValidRow)
	{
		int rows = this.getWorkflowDao().updateEntity(sql, "WorkflowSql.updateWorkflowRelatedStatus");
		if (isValidRow)
		{
			if (rows<=0 || rows>=50)
			throw new ProcedureException("更新单据状态发生错误,操作失败!");
		}
	}
	
	//执行动作
	private void execAction(WorkflowTemplateNodeAction action,WorkflowInstance wi)
	{
		if(ValidateUtils.isNotNull(action.getSqlcont())){
			if(wi.getBusid()>0){
				Map p =createLoginMap();
				p.put("wiid", wi.getWiid());
				p.put("nodeid", action.getNodeid());
				p.put(wi.getFieldname(),wi.getBusid());
				getJdao().execute(p,action.getSqlcont());
				
				
			}
		}
		else{
			//1=更新节点状态，2=更新业务单据状态
			String sql = "";
			if (action.getType()==1)
			{
				sql = "update t_workflow_instance_node set isend="+action.getNewstatus()+" where winid in (select winid from t_workflow_instance_node where wiid="+wi.getWiid()+" and nodeid="+action.getUpdatednodeid()+") and isend="+action.getOldstatus();
				
			}
			if (action.getType()==2)
			{
				
					Map appidMap = this.dynamicQueryForMap("select appid from t_workflow_template_definition where wtdid="+wi.getWtdid());
					Map appMap = this.dynamicQueryForMap("select dbname from v_app where id="+appidMap.get("appid"));
					
					sql = "update "+appMap.get("dbname")+"."+wi.getBustblname()+" set "+wi.getStatusname()+"="+action.getNewstatus()+" where "+wi.getFieldname()+"="+wi.getBusid()+" and "+wi.getStatusname()+"="+action.getOldstatus();
				
			}
	//		if (action.getType()==3)
	//		{
	//			sql = "update "+wi.getBustblname()+" set flowstatus=0 where "+wi.getFieldname()+"="+wi.getBusid()+" and flowstatus=1";
	//		}
			if(action.getType()==1||wi.getBusid()>0)
			execUpdateSql(sql,true);
		}
	}
	
	//回写单据流程状态
	private void callbackBusiness(WorkflowInstance wi)
	{
		//1=更新节点状态，2=更新业务单据状态
//		String sql = "";
//		sql = "update "+wi.getBustblname()+" set flowstatus=1,flowid="+wi.getWiid()+" where "+wi.getFieldname()+"="+wi.getBusid()+" and flowstatus=0";
//		if(wi.getBusid()>0)
//			execUpdateSql(sql,true);
	}	
	
	//不需要启动流程,无流程配置(flowstatus=(0:未启动,1:已启动),flowid)
	private void skipWorkflow(StartFlowDTO dto)
	{
		
		//获取库名
		//Map appMap = this.dynamicQueryForMap("select id,name,rank,pre,dbname from v_app where id="+dto.getAppid());
		//String sql = "update "+appMap.get("dbname")+"."+dto.getBustblname()+" set "+dto.getStatusname()+"="+dto.getNewstatus()+" where "+dto.getFieldname()+"="+dto.getBusid()+" and "+dto.getStatusname()+"="+dto.getOldstatus();
		String sql = dto.getSqlcont();
		
		
		Map p = createLoginMap();
		p.put(dto.getFieldname(), dto.getBusid());
		//p.put(Constants.LOGIN_ID,RequestProcessorUtils.getUser(ServletActionContext.getRequest()).getManid());
		//p.put(wi.getFieldname(),wi.getBusid());
		//	String cont = condition.getSqlcont()+"";
		 
		//return ValidateUtils.isNotNull(jdao.queryForList(p,cont));
		
		if(dto.getBusid()>0 && StringUtils.isNotEmpty(sql)){
			jdao.execute(p, sql);
		}else{
			throw new ProcedureException("流程模版未正确配置sql表达式或业务ID为空!");
		}
			//execUpdateSql(sql,true);
	}
	

	
	//插入节点,不管是否启动
	private WorkflowInstanceNode initNode(WorkflowTemplateNode node,WorkflowInstance wi)
	{
		int isEnd = 0;
		//节点不满足启动条件
		WorkflowInstanceNode win = null;
		
		//如果不存在该节点数据，生成节点数据，否则更新节点状态为执行中
		WorkflowInstanceNode existInsNode = this.getWorkflowDao().getWorkflowInstanceNoFinNodeByNodeId(wi.getWiid(),node.getNodeid());
		if (null==existInsNode)
		{
			win = insertNodeData(node,wi,isEnd);
		}else
		{
			existInsNode.setIsend(isEnd);
			win = existInsNode;
			win.setDao(this.getWorkflowDao());
			win.updateToExecStatus();
		}
		return win;
	}
	
	
	private void sendSMS(final WorkflowInstanceNode node, final WorkflowInstance wi) {

		if (node != null && ( node.getType() == 3 || node.getType()==2)&& node.getIsend() > 0 && wi != null) {
			final Map p = createLoginMap();
			new Thread() {
				public void run() {
					try{
						// 人工节点
						List<WorkflowInstanceVariable> l = getWorkflowDao().getWorkflowInstanceVariableByWiId(wi.getWiid());
						for (int i = 0; i < l.size(); i++) {
							p.put(l.get(i).getEname(), l.get(i).getValue());
						}
						p.put("wiid", wi.getWiid());
						p.put("nodeid", node.getNodeid());
						p.put(wi.getFieldname(), wi.getBusid());

						Tools.createXML(p);
						List<Map> mans = getJdao().queryForList(p, "{call sp_workflow_sendSMS(#logonid:integer#,#xml:varchar#)} ");
						//Thread.sleep(Constants.SMS_WAIT);
						for (Map man : mans) {
							String tel = (String) ConvertUtils.convert(man.get("tel"), String.class);
							String smscontent = (String) ConvertUtils.convert(man.get("smscontent"), String.class);
							if (StringUtils.isNotEmpty(tel)) {
								try {
									//SMSSender.sendSMS("", tel, smscontent);
									//Thread.sleep(1000);
									SMSService.addSMS(tel, smscontent);
								} catch (Exception e) {
									log.error(tel+",发送短信失败", e);
								}
							}
						}
					} catch (Exception e) {
						log.error("发送短失败", e);
					}
					
				}
			}.start();
		}
	}
	
	private void sendOtherSMS(final WorkflowInstanceNode node, final WorkflowInstance wi) {

		if (node != null &&  node.getType() == 3 && node.getIsend() > 0 && wi != null) {
			final Map p = createLoginMap();
			new Thread() {
				public void run() {
					try {
						// 人工节点
						List<WorkflowInstanceVariable> l = getWorkflowDao().getWorkflowInstanceVariableByWiId(wi.getWiid());
						for (int i = 0; i < l.size(); i++) {
							p.put(l.get(i).getEname(), l.get(i).getValue());
						}
						p.put("wiid", wi.getWiid());
						p.put("nodeid", node.getNodeid());
						p.put(wi.getFieldname(), wi.getBusid());

						Tools.createXML(p);
						List<Map> mans = getJdao().queryForList(p, "{call sp_workflow_sendSMS_other(#logonid:integer#,#xml:varchar#)} ");
						for (Map man : mans) {
							String tel = (String) ConvertUtils.convert(man.get("tel"), String.class);
							String smscontent = (String) ConvertUtils.convert(man.get("smscontent"), String.class);
							if (StringUtils.isNotEmpty(tel)) {
								try {
									//SMSSender.sendSMS("", tel, smscontent);
									SMSService.addSMS(tel, smscontent);
								} catch (Exception e) {
									log.error(tel + ",抄送短信失败", e);
								}
							}
						}
					} catch (Exception e) {
						log.error("抄送短信失败", e);
					}
				}
			}.start();
		}
	}
	
	// 节点启动
	private WorkflowInstanceNode startNode(WorkflowTemplateNode node,WorkflowInstance wi)
	{
		
		boolean isStart=false;
		if (node.isStart())
		{
			isStart = true;
		}else
		{
			//判断条件,决定是否启动
			List<WorkflowTemplateCondition> conditions = this.getWorkflowDao().getWorkflowTemplateConditionType1ByNodeId(node.getNodeid());
			isStart = isType1Condition(conditions,wi);
			
		}
		
		
		
		int isEnd = 1;
		//节点不满足启动条件
		if (!isStart) isEnd = 0;
		
		WorkflowInstanceNode win = null;
		
		//如果不存在该节点数据，生成节点数据，否则更新节点状态为执行中
		WorkflowInstanceNode existInsNode = this.getWorkflowDao().getWorkflowInstanceNoFinNodeByNodeId(wi.getWiid(),node.getNodeid());
		if (null==existInsNode)
		{
			win = insertNodeData(node,wi,isEnd);
		}else
		{
			existInsNode.setIsend(isEnd);
			win = existInsNode;
			win.setDao(this.getWorkflowDao());
			win.updateToExecStatus();
		}

		
		
		
		//根据节点类型确认是否直接结束，人工节点需要人工确认结束。
		if (!node.isMenual()&&isEnd==1)
		{
			endNode(win,wi,null,null,0);
		}
		
		//短信发送
		if (isStart) {
			sendSMS(win, wi);
		}
		 
		
		return win;
	}	
	
	//节点结束
	private void endNode(WorkflowInstanceNode win,WorkflowInstance wi,String note,String chkret,int manid)
	{
		//结束节点
		win.setIsend(2);
		win.setNote(note);
		win.setManid(manid);
		win.setChkret(chkret);
		int rows = win.update();
		if (rows!=1){
			int nodeid = win.getNodeid();
			throw new ProcedureException("更新节点结束状态发生错误,操作失败!,nodeid->"+nodeid);
		}else{
			sendOtherSMS(win,wi);
		}
		
		
		WorkflowInstanceNode tempNode=null;
		
		//跳转节点处理
		try {
			Map reqParams = RequestContext.getNodeParams();
			int reqNodeid = (Integer) ConvertUtils.convert(reqParams
					.get("nodeid"), Integer.class);
			if (reqNodeid > 0) {
				//检查该节点，是否在该模版之下
				Map model = this.dynamicQueryForMap("select 1 from t_workflow_template_node  where wtdid="+wi.getWtdid()+" and nodeid="+reqNodeid);
				if(model==null || model.isEmpty()){
					throw new ProcedureException("流程代码 "+wi.getWtdcode()+"或节点ID"+reqNodeid+" 不存在!");
				}
				
				WorkflowInstanceNode existInsNode = this.getWorkflowDao()
						.getWorkflowInstanceNoFinNodeByNodeId(wi.getWiid(),
								reqNodeid);
				if (null == existInsNode) {
					WorkflowTemplateNode startNode = (WorkflowTemplateNode) this
							.queryForObject(reqNodeid,
									"WorkflowSql.selectWorkflowTemplateStartNodeByNodeId");
					win = insertNodeData(startNode, wi, 1);
				}
				if(win!=null){
					sendSMS(win,wi);
				}
			}
		} catch (Exception e) {
			log.error("跳转节点", e);
		}
		
		

		//生成下一节点,插入转出线
		List<WorkflowTemplateTransition> transitions = this.getWorkflowDao().getWorkflowTemplateTransitionsByFirstNodeId(win.getNodeid());
		for (int i=0;i<transitions.size();i++)
		{
			//如果下一节点未生成，生成下一节点，否则根据启动条件确定是否生成该节点。
			WorkflowTemplateNode node = this.getWorkflowDao().getWorkflowTemplateNextNodeByTrId(transitions.get(i).getTrid());
			WorkflowInstanceNode newWin = initNode(node,wi);
			insertTransitionData(transitions.get(i),win,newWin,wi);
			startNode(node,wi);
			tempNode=newWin;
			
		}		
		
		//根据操作条件,确认是否执行操作
		List<WorkflowTemplateNodeAction> actions = this.getWorkflowDao().getWorkflowTemplateNodeActionsByNodeId(win.getNodeid());
		for (int i=0;i<actions.size();i++)
		{
			List<WorkflowTemplateCondition> conditions = this.getWorkflowDao().getWorkflowTemplateConditionType2ByActionId(actions.get(i).getActionid());
			boolean isExecAction = isType2Condition(conditions,wi);
			if (isExecAction)
			{
				execAction(actions.get(i),wi);
			}
		}
		
		//更新相关的转入连线状态
		List<WorkflowInstanceTransition> witrs = this.getWorkflowDao().getWorkflowInstanceTransitionByTnId(win.getWinid());
		for(int i=0;i<witrs.size();i++)
		{
			witrs.get(i).setDao(this.getWorkflowDao());
			witrs.get(i).update();
		}
		
		//结束更新流程状态,更新所有未存在的节点为未执行,更新未存在的画线
		if (win.isEnd())
		{
			stopWorkFlow(wi,0);
			
			//更新实例，处理状态，如：同意，拒绝
			updateExec(wi);
		}
		
		
	}
	
	//确认实例节点是否存在
	private boolean isExistInstanceNode(WorkflowTemplateNode node,List<WorkflowInstanceNode> list)
	{
		for (WorkflowInstanceNode o:list)
		{
			if (o.getNodeid()==node.getNodeid())
				return true;
		}
		
		return false;
	}
	
	//确认实例Transition是否存在
	private boolean isExistInstanceTransition(WorkflowTemplateTransition trans,List<WorkflowInstanceTransition> list)
	{
		for (WorkflowInstanceTransition o:list)
		{
			if (o.getTrid()==trans.getTrid())
				return true;
		}
		
		return false;
	}
	
	//结束流程
	private void stopWorkFlow(WorkflowInstance wi,Integer stopUser)
	{
		wi.setDeluser(stopUser);
		wi.setDao(this.getWorkflowDao());
		int rows = wi.update();
		if (rows!=1)
			throw new ProcedureException("更新流程结束状态发生错误,操作失败!");		
		
		//将流程未涉及到的节点保存入流程实例表中
		List<WorkflowTemplateNode> tempNodeList = this.getWorkflowDao().getWorkflowTemplateNodeByWtdId(wi.getWtdid());
		List<WorkflowInstanceNode> insNodeList =  this.getWorkflowDao().getWorkflowInstanceNodeByWiId(wi.getWiid());
		for (int i=0;i<tempNodeList.size();i++)
		{
			if (!isExistInstanceNode(tempNodeList.get(i),insNodeList))
			{
				initNode(tempNodeList.get(i),wi);
			}
		}
		
		
		//将流程未涉及到的连线保存入流程实例表中
		List<WorkflowTemplateTransition> tempTransList = this.getWorkflowDao().getWorkflowTemplateTransitionsByWtdId(wi.getWtdid());
		List<WorkflowInstanceTransition> insTransList = this.getWorkflowDao().getWorkflowInstanceTransitionByWiId(wi.getWiid());
		for (WorkflowTemplateTransition trans:tempTransList)
		{
			if (!isExistInstanceTransition(trans,insTransList))
			{
				WorkflowInstanceNode fInsNode = this.getWorkflowDao().getWorkflowInstanceNodeByNodeId(wi.getWiid(),trans.getFnid());
				WorkflowInstanceNode tInsNode = this.getWorkflowDao().getWorkflowInstanceNodeByNodeId(wi.getWiid(),trans.getTnid());
				insertTransitionData(trans,fInsNode,tInsNode,wi);
			}
		}
	}
	
	public Map createLoginMap(){
		Map params = new HashMap();
		try{
			int loginid = RequestProcessorUtils.getUser(ServletActionContext.getRequest()).getManid();
			if(loginid<0){
				loginid = RequestContext.getAppLogonid();
			}
			params.put(Constants.LOGIN_ID,loginid);
		}catch (Exception e) {
			log.error(e);
		}
		
		return params;
	}
	
	public void updateExec(WorkflowInstance wi){
		try{
			WorkflowInstanceVariable var = wi.getExecVar();
			
			
			Map params  = createLoginMap();
			params.put("wiid", wi.getWiid());
			if(var!=null){
				params.put("wivarid", var.getWivarid());
			}else{
				params.put("wivarid", 0);
			}
			Tools.createXML(params);
			this.getJdao().execute(params, "{call sp_workflow_update_exec_status(#logonid:integer#,#xml:varchar#)} ");
		}catch (Exception e) {
			log.error("流程结束,更新状态:"+e);
		}
	}
	
	public void forceStopWorkflow(int wiid,int logonid)
	{
		WorkflowInstance wi = this.getWorkflowDao().getWorkflowInstanceById(wiid);
		//更新所有节点状态
		String sql = "update t_workflow_instance_node set isend=2,enddt=getdate() where wiid="+wiid+" and isend in(0,1)";
		execUpdateSql(sql,false);
		
		//结束流程
		stopWorkFlow(wi,logonid);
		
		updateExec(wi);
		
		//还原业务单据状态
//		sql = "update "+wi.getBustblname()+" set flowstatus=0 where "+wi.getFieldname()+"="+wi.getBusid()+" and flowstatus=1";
//		if(wi.getBusid()>0)
//		execUpdateSql(sql,true);
	}
	
	//流程启动
	public void startWorkFlow(StartFlowDTO dto){
		//检查流程是否存在
		Map model = checkWtdcode(dto.getWtdcode());
		
		 
		
		
		
		
		
		//String sql = "update "+dto.getBustblname()+" set "+dto.getStatusname()+"="+dto.getNewstatus()+" where "+dto.getFieldname()+"="+dto.getBusid()+" and "+dto.getStatusname()+"="+dto.getOldstatus();
		dto.setBustblname((String)ConvertUtils.convert(model.get("bustblname"),String.class));
		dto.setStatusname((String)ConvertUtils.convert(model.get("statusname"),String.class));
		dto.setFieldname((String)ConvertUtils.convert(model.get("fieldname"),String.class));
		dto.setAppid((String)ConvertUtils.convert(model.get("appid"),String.class));
		dto.setSqlcont((String)ConvertUtils.convert(model.get("sqlcont"),String.class));
		
		
		
		
		
		//找到流程模板,无模板直接更新为已审批状态,结束
		WorkflowTemplateDefinition wtd = this.getWorkflowDao().getWorkflowTemplateDefinitionByWtdcode(dto.getWtdcode());
		//直接更新表单状态为已审批.
		if (null==wtd)
		{
			
			skipWorkflow(dto);
			return;
		}
		
		if(dto.getBusid()>0){
			if(CommonProcessor.isExistForSql(this,"select 1 where 1=dbo.gf_flow_isexec('"+wtd.getBustblname()+"','"+dto.getBusid()+"')")){
				throw new ProcedureException("该单据已存在执行中的工作流,不得重新提交!");
			}
		}
		
		//新建流程实例
		WorkflowInstance wi = new WorkflowInstance();
		wi.setBusid(dto.getBusid());
		wi.setBustblname(wtd.getBustblname());
		wi.setStatusname(wtd.getStatusname());
		wi.setFieldname(wtd.getFieldname());
		wi.setIsend(1);
		wi.setIsreload(false);
		wi.setWtdid(wtd.getWtdid());
		wi.setWtd(wtd);
		wi.setDao(this.getWorkflowDao());
		wi.setCreateuser(dto.getLogonid());
		wi.setCompid(dto.getCompid());
		wi.setDeptid(dto.getDeptid());
		wi.setWtdcode(dto.getWtdcode());
		wi.insert();
		
		
		Map params  = new HashMap();
		params.put("logonid", dto.getLogonid());
		params.put("wiid", wi.getWiid());
		try{
			Tools.createXML(params);
			this.getJdao().execute(params, "{call sp_workflow_update_smscontent(#logonid:integer#,#xml:varchar#,#errmsg:varchar:inout#)} ");
		}catch (Exception e) {
			log.error(e);
		}
		
		
		//更新业务单据数据;
		callbackBusiness(wi);
		
		
		//新建流程变量实例，根据DTO更新流程实例变量值
		List<WorkflowTemplateVariable> variables = this.getWorkflowDao().getWorkflowTemplateVariablesByWtdId(wtd.getWtdid());
		for(int i=0;i<variables.size();i++)
		{
			insertInstanceVariableData(variables.get(i),dto.getVariables(),wi);
		}
		
		
		//寻找开始节点，无条件执行
		WorkflowTemplateNode startNode = this.getWorkflowDao().getWorkflowTemplateStartNodeByWtdId(wtd.getWtdid());
		startNode(startNode,wi);
	}

	private Map checkWtdcode(String wtdcode) {
		Map model = this.dynamicQueryForMap("select wtdid,name,bustblname,fieldname,statusname,version,url,status,createuser,createdt,deluser,deldt,appid,sqlcont from t_workflow_template_definition where wtdcode='"+wtdcode+"'");
		
		if(model==null){
			throw new ProcedureException("流程代码 "+wtdcode+" 不存在!");
		}
		return model;
	}
	
	//取得人工节点确认的Form
	public GoToNextForm getGoToNextFormByWinid(int winid)
	{
		GoToNextForm form = new GoToNextForm();
		WorkflowInstanceNode insNode = this.getWorkflowDao().getWorkflowInstanceNodeById(winid);
		form.setWinid(winid);
		form.setVarid(insNode.getVarid());
		form.setVariables(this.getWorkflowDao().getMenualOptionsByNodeid(insNode.getNodeid()));
		return form;
	}	
	
	//流程转下
	public void gotoNext(GoToNextDTO dto)
	{
		WorkflowInstanceNode win = this.getWorkflowDao().getWorkflowInstanceNodeById(dto.getWinid());
		win.setDao(this.getWorkflowDao());
		WorkflowInstance wi = this.getWorkflowDao().getWorkflowInstanceById(win.getWiid());
		
		wi.setDao(this.getWorkflowDao());
		
		//更新变量值，调用END
		List<WorkflowInstanceVariable> variables = this.getWorkflowDao().getWorkflowInstanceVariableByWiId(wi.getWiid());
		for (int i=0;i<variables.size();i++)
		{
			if (!variables.get(i).isCoust())
			{
				replaceVarDataValue(variables.get(i),dto.getVariables());
				variables.get(i).setDao(this.getWorkflowDao());
				variables.get(i).update();
			}
		}
		
		//更新人工返回结果的值
		int varid = dto.getVarid();
		if (varid>0)
		{
			WorkflowInstanceVariable var = this.getWorkflowDao().getWorkflowInstanceVariableByWiidAndVarid(wi.getWiid(), varid);
			
			if (var==null)
			{
				throw new ProcedureException("变量参数传递有误,操作失败!");
			}
			
			var.setValue(dto.getValue());
			var.setDao(this.getWorkflowDao());
			var.update();
			
			
			wi.setExecVar(var);
			
		}
		
		String chkret = this.getWorkflowDao().getChkretByNodeidAndValue(win.getNodeid(), dto.getValue());
		
		endNode(win,wi,dto.getNote(),chkret,dto.getLogonid());
	}
	

	
	public void addTemplateVariableByNode(Map params, List<Map> dtls) {
		 
		checkTemplateIsStop(params);
		
		
		//this.getDao().deleteEntity(params, "WorkflowSql.delTemplateVariableByWtdid");
		for(Map m : dtls){
			this.insertEntity(m, "WorkflowSql.addWorkTemplateVariable");
		}
	}

	public void addWorkTemplateVariable(Map params) {
		this.insertEntity(params, "WorkflowSql.addWorkTemplateVariable");
	}

	public void addNodeOption(Map params) { 
		checkTemplateIsStop(params);
		this.insertEntity(params, "WorkflowSql.addNodeOption");
	}

	public void saveWorkFlowToServer(Map template) {
		checkTemplateIsStop(template);
		
		JSONArray nodesArr = (JSONArray) template.get("nodes");
		JSONArray linesArr = (JSONArray) template.get("lines");
		
		List<Map> nodes	= JSONArray.parseArray(nodesArr.toJSONString(), Map.class);
		
		List<Map> lines	= JSONArray.parseArray(linesArr.toJSONString(), Map.class);
		
		for(Map m : nodes){
			this.updateEntity(m, "WorkflowSql.update_t_workflow_template_node_x_y");
		}
		
		for(Map m : lines){
			m.put("logonid", template.get("logonid"));
			int trid = (Integer) ConvertUtils.convert(m.get("trid"),Integer.class);
			if(trid>0){
				//更新
				this.updateEntity(m, "WorkflowSql.udpate_t_workflow_template_transition");
			}else{
				//添加
				this.insertEntity(m, "WorkflowSql.insert_t_workflow_template_transition");
			}
		}
		
		
	}

	public void delTemplateNodeById(Map params) {
		checkTemplateIsStop(params);
		
		String sql = "select 1 from t_workflow_template_transition where fnid="+params.get("nodeid")+" or tnid="+params.get("nodeid");
		if(CommonProcessor.isExistForSql(this, "select 1 from t_workflow_template_node_action where nodeid="+params.get("nodeid")+" or updatednodeid="+params.get("nodeid"))){
			throw new ProcedureException("该线节点已被执行操作使用,操作失败!");
		}
		
		if(CommonProcessor.isExistForSql(this, sql)){
			throw new ProcedureException("该节点存在未删除的线,操作失败!");
		}
		
		
		
		//删除选项
		this.getDao().deleteEntity(params, "WorkflowSql.delTemplateNodeById_option");
		
		//删除条件
		this.getDao().deleteEntity(params, "WorkflowSql.delTemplateNodeById_condition");
		
		
		//删除操作人
		this.getDao().deleteEntity(params, "WorkflowSql.delTemplateNodeById_operator");
		 
		
		this.updateEntity(params, "WorkflowSql.delTemplateNodeById");
	}

	private void checkTemplateIsStop(Map params) {
//		if(!CommonProcessor.isExistForSql(this, "select 1 from t_workflow_template_definition where wtdid="+params.get("wtdid")+" and status=0")){
//			throw new ProcedureException("只有已停用的模版才能执行该操作,操作失败!");
//		}
	}

	public void delTemplateTransitionById(Map params) {
		checkTemplateIsStop(params);
		if(CommonProcessor.isExistForSql(this, "select 1 from t_workflow_template_condition where trid="+params.get("trid"))){
			throw new ProcedureException("该线已被启动条件使用,操作失败!");
		}
		this.updateEntity(params, "WorkflowSql.delTemplateTransitionById");
	}

	public void addWorkTemplateNodeAction(Map params) {
		checkTemplateIsStop(params);
		this.insertEntity(params, "WorkflowSql.addWorkTemplateNodeAction");
	}

	public void editWorkTemplateNodeAction(Map params) {
		checkTemplateIsStop(params);
		this.updateEntity(params, "WorkflowSql.modWorkTemplateNodeAction");
	}

	public void addWorkTemplateNodeCondition(Map params) {
		checkTemplateIsStop(params);
		if(ValidateUtils.isNull(params.get("varid1"))){
			params.put("varid1",0);
		}
		if(ValidateUtils.isNull(params.get("varid2"))){
			params.put("varid2",0);
		}
		if(ValidateUtils.isNull(params.get("condsign"))){
			params.put("condsign",0);
		}
		if(ValidateUtils.isNull(params.get("joinsign"))){
			params.put("joinsign",1);
		}
		this.insertEntity(params, "WorkflowSql.addWorkTemplateNodeCondition");
	}

	public void editWorkTemplateNodeCondition(Map params) {
		checkTemplateIsStop(params);
		if(ValidateUtils.isNull(params.get("varid1"))){
			params.put("varid1",0);
		}
		if(ValidateUtils.isNull(params.get("varid2"))){
			params.put("varid2",0);
		}
		if(ValidateUtils.isNull(params.get("condsign"))){
			params.put("condsign",0);
		}
		if(ValidateUtils.isNull(params.get("joinsign"))){
			params.put("joinsign",1);
		}
		this.insertEntity(params, "WorkflowSql.editWorkTemplateNodeCondition");
	}

	public void addWorkTemplateNodeOperator(Map params) {
			//this.getDao().deleteEntity(params,"WorkflowSql.deleteWorkTemplateNodeOperatorByNode");
			String manidsStr = (String) params.get("manids");
			String deptidsStr = (String) params.get("deptids");
			
			if(StringUtils.isEmpty(deptidsStr)){
				deptidsStr="0";//如果没有选择部门，默认为0
				
			}
			
			if(manidsStr!=null ){
				String[] manids = manidsStr.split(",");
				String[] deptids = deptidsStr.split(",");
				
				for(int i=0;i<deptids.length;i++){
					
					for(int j=0;j<manids.length;j++){
						params.put("manid", ConvertUtils.convert(manids[j], Integer.class));
						params.put("deptid", ConvertUtils.convert(deptids[i], Integer.class));
						String sql="select 1 from t_workflow_template_node_operator where nodeid="+params.get("nodeid")+" and manid="+params.get("manid")+" and   deptid="+params.get("deptid");
						if(!CommonProcessor.isExistForSql(this, sql)){
							this.insertEntity(params, "WorkflowSql.addWorkTemplateNodeOperator_new");
						}
						
					}
				}
				
			}
			
			//this.insertEntity(params, "WorkflowSql.addWorkTemplateNodeOperator");
	}

	public void editWorkTemplateNode(Map params) {
//		if(!CommonProcessor.isExistForSql(this, "select 1 from t_workflow_template_definition where wtdid="+params.get("wtdid")+" and status=0")){
//			throw new ProcedureException("该模版已经启动,禁止修改!");
//		}
		//and exists(select 1 from t_workflow_template_definition where wtdid=#wtdid:integer# and status=0)
		this.updateEntity(params, "WorkflowSql.editWorkTemplateNode");
	}

	public void workTemplateStart(Map params) {
//		if(!CommonProcessor.isExistForSql(this, "select 1 from t_workflow_instance where wtdid="+params.get("wtdid")+" and isend=1")){
//			throw new ProcedureException("该模版已经存已启动的流程实例,禁止修改!");
//		}
		this.updateEntity(params, "WorkflowSql.workTemplateStart");
	}

	public void workTemplateCancel(Map params) {
		this.updateEntity(params, "WorkflowSql.workTemplateCancel");
	}	
	
	public void workTemplateStop(Map params) {
//		if(CommonProcessor.isExistForSql(this, "select 1 from t_workflow_instance where wtdid="+params.get("wtdid")+" and isend=1")){
//			throw new ProcedureException("该模版已经存已启动的流程实例,禁止修改!");
//		}
		this.updateEntity(params, "WorkflowSql.workTemplateStop");
	}

	public void delNodeOption(Map params) {
		checkTemplateIsStop(params);
		this.updateEntity(params, "WorkflowSql.delNodeOption");		
	}

	public void delWorkTemplateNodeCondition(Map params) {
		checkTemplateIsStop(params);
		this.updateEntity(params, "WorkflowSql.delWorkTemplateNodeCondition");		
	}

	public void delWorkTemplateNodeAction(Map params) {
		checkTemplateIsStop(params);
		//条件
		if(CommonProcessor.isExistForSql(this, "select 1 from t_workflow_template_condition where actionid="+params.get("actionid"))){
			throw new ProcedureException("该节点已被启动条件使用,操作失败!");
		}
		
		this.updateEntity(params, "WorkflowSql.delWorkTemplateNodeAction");		
	}

	public Object addWorkTemplateNode(Map params) {
		checkTemplateIsStop(params);
		Object id  =this.insertEntity(params, "WorkflowSql.insert_t_workflow_template_node");
		return id;
	}
	
	public void deleteWorkflowTemplateVariable(Map params) {
		checkTemplateIsStop(params);
		
		//节点
		if(CommonProcessor.isExistForSql(this, "select 1 from t_workflow_template_node where varid="+params.get("varid"))){
			throw new ProcedureException("该变量已被节点使用,操作失败!");
		}
		//选 项
		if(CommonProcessor.isExistForSql(this, "select 1 from t_workflow_template_node_option where varid="+params.get("varid"))){
			throw new ProcedureException("该变量已被节点操作选项使用,操作失败!");
		}
		//选 项
		if(CommonProcessor.isExistForSql(this, "select * from t_workflow_template_condition where varid1="+params.get("varid")+" and varid2="+params.get("varid"))){
			throw new ProcedureException("该变量已被节点启动条件使用,操作失败!");
		}
		
		this.updateEntity(params, "WorkflowSql.deleteWorkflowTemplateVariable");
	}	
	
	public void editWorkflowTemplateVariable(Map params) {
		checkTemplateIsStop(params);
		this.updateEntity(params, "WorkflowSql.updateWorkflowTemplateVariable");
	}

	public void addWorkTemplate(Map params) {
		
		Object wtdid = this.insertEntity(params, "WorkflowSql.insert_t_workflow_template_definition");
		params.put("wtdid", wtdid);
		Tools.createXML(params);
		this.getJdao().execute(params, "{call sp_workflow_check_template(#logonid:integer#,#errmsg:varchar:inout#,#xml:varchar#)}  ");
	}

	public void editWorkTemplate(Map<String, Object> params) {
		this.updateEntity(params, "WorkflowSql.update_t_workflow_template_definition");
		this.getJdao().execute(params, "{call sp_workflow_check_template(#logonid:integer#,#errmsg:varchar:inout#,#xml:varchar#)}  ");
	}		

}
